﻿using System;
using System.Windows;
using System.Windows.Controls;
using Babylon.Animations;
using Babylon.Primitives;
using Babylon.Toolbox;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Silverlight;

namespace Babylon.Toolkit.AnimationsSample
{
    public partial class MainPage
    {
        private readonly OrbitCamera _camera;

        private readonly ColoredCube _floor;
        private VertexColorEffect _floorEffect, _ballEffect;
        private readonly ColoredEllipse _ball;
        private readonly IMatrixAnimation _ballAnim;
        public MainPage()
        {
            InitializeComponent();
            _camera = new OrbitCamera {Radius = 20};
            _camera.AttachTo(inputSurface);

            _floor = new ColoredCube(200, 2, 200, new Color(0, 0.6f, 0, 1));
            _ball = new ColoredEllipse(1, 1, 20, new Color(0.7f, 0.7f, 0, 1.0f));
            var bounding = new MatrixAnimationUsingKeyFrames
            {
                BaseValue = Matrix.CreateTranslation(0, 30, 0),
                GlobalEasingFunction = n => n*n,
                RepeatForever = true
            };
            bounding.AddKeyFrame(new KeyFrame<Matrix>(0.5f, Matrix.CreateTranslation(0, 1, 0), n => n * n * n));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(1, Matrix.CreateTranslation(0, 20, 0), n => (float)Math.Pow(n, 0.33)));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(1.5f, Matrix.CreateTranslation(0, 1, 0), n => n * n * n));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(2, Matrix.CreateTranslation(0, 13, 0), n => (float)Math.Pow(n, 0.33)));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(2.5f, Matrix.CreateTranslation(0, 1, 0), n => n * n * n));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(3, Matrix.CreateTranslation(0, 9, 0), n => (float)Math.Pow(n, 0.33)));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(3.5f, Matrix.CreateTranslation(0, 1, 0), n => n * n * n));
            bounding.AddKeyFrame(new KeyFrame<Matrix>(4, Matrix.CreateTranslation(0, 1, 0)));
            _ballAnim = new CombinedMatrixAnimation
            {
                MatrixAnimations = 
                {
                    new MatrixAnimation
                    {
                        
                        AutoReverse = true,
                        BaseValue = Matrix.CreateScale(1, 2, 1),
                        Duration = 0.5f,
                        RepeatForever = true,
                        ToValue = Matrix.CreateScale(2, 1, 2)
                    },
                    new MatrixAnimation
                    {
                        RepeatForever = true,
                        BaseValue = Matrix.CreateTranslation(100, 0, 0),
                        Duration = 4,
                        ToValue = Matrix.CreateTranslation(-100, 0, 0)
                    },
                    bounding
                }
            };
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            var gd = GraphicsDeviceManager.Current.GraphicsDevice;
            _floor.Device = gd;
            _ball.Device = gd;
            _floorEffect = new VertexColorEffect(gd);
            _floor.Effect = _floorEffect;
            _ballEffect = new VertexColorEffect(gd);
            _ball.Effect = _ballEffect;
            _floor.LoadContent();
            _ball.LoadContent();

            _floorEffect.AmbientColor = new Color(0.2f, 0.2f, 0.2f, 1.0f);
            _floorEffect.LightPosition = new Vector3(100, 1000, 10);
            _floorEffect.SceneAmbientColor = new Color(0.2f, 0.2f, 0.2f, 1.0f);
            _floorEffect.World = Matrix.CreateTranslation(0, -1, 0);



            _ballEffect.AmbientColor = new Color(0.5f, 0.5f, 0.5f, 1.0f);
            _ballEffect.LightPosition = new Vector3(100, 1000, 10);
            _ballEffect.SceneAmbientColor = new Color(0.5f, 0.5f, 0.5f, 1.0f);
            _ballEffect.World = Matrix.CreateTranslation(0, 10, 0);
        }

        private void OnAspectRatioChanged(object sender, SizeChangedEventArgs e)
        {
            _camera.AspectRatio = e.NewSize.AspectRatio();
        }

        private void OnDraw(object sender, DrawEventArgs e)
        {
            if (_ballAnim.AnimationState == AnimationState.Stopped)
            {
                _ballAnim.Start((float)e.TotalTime.TotalSeconds);
            }
            else
            {
                _ballAnim.Update((float)e.TotalTime.TotalSeconds);
            }
            var gd = e.GraphicsDevice;
            gd.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(120, 120, 120, 255), 1, 0);
            _ball.Device = gd;
            _ballEffect.Device = gd;
            _floor.Device = gd;
            _floorEffect.Device = gd;

            _floorEffect.CameraPosition = _camera.Position;
            _ballEffect.CameraPosition = _camera.Position;
            _floorEffect.Projection = _camera.Projection;
            _ballEffect.Projection = _camera.Projection;
            _floorEffect.View = _camera.View;
            _ballEffect.View = _camera.View;
            _ballEffect.World = _ballAnim.CurrentValue;

            _ball.Draw();
            _floor.Draw();

            _camera.ApplyInertia();
            e.InvalidateSurface();
        }
    }
}
